# Author:Yiye
# -*- codeing = utf-8 -*-
# @Time :2021/11/29 1:15
# @Author:李卓
# @Site : 
# @File : 学生选课系统.py
# @Software : PyCharm
# -*- coding: UTF-8 -*-
import pymysql


class mysql():

    def __init__(self, address, port, user, passwd, char_set):
        """
        Function: 类的初始化函数，数据库对象mysql在初始化时直接连接数据库，并获取cursor对象
        args:
            self:类对象
            address:要连接的数据库ip地址
            port:要连接的数据库端口
            user:连接数据库用户名
            passwd:连接数据库密码
            char_set:连接用字符集，一般为"utf8"(默认)
        return: None
        """
        try:
            self.database = pymysql.connect(host=address, user=user, passwd=passwd, charset=char_set, port=port)
            self.cursor = self.database.cursor()
            self.cursor.execute("use student_info")
        except Exception as e:
            print("Connection failed!")
            print(e)
            exit(-1)

    def is_admin(self, admin_name):
        """
        func:判断用户名admin_name是不是管理员账户
        args:
            admin_name:需要判断的账户名
        return:
            True/False
        """

        if self.cursor.execute("select * from admin where username=\"%s\"" % admin_name) == 0:
            return False
        return True

    def is_admin_passwd_correct(self, username, passwd):
        """
        func:判断用户名username的密码是否为passwd
        args:
            admin_name:需要判断的账户名
            passwd:需要判断的密码
        return:
            True/False
        """
        self.cursor.execute("select * from admin where username=\"%s\"" % username)
        if self.cursor.fetchall()[0][1] == passwd:
            return True
        return False

    @staticmethod
    def username2int(input_username_str):
        """
        func:把非管理员类的用户名，即学生学号，由字符串转为int
        args:
            input_username_str:需要转换的用户名
        return:
            int
        """

        try:
            input_username_int = int(input_username_str)
        except:
            return None
        return input_username_int

    @staticmethod
    def is_empty_input(str1, str2):
        """
        func:判断输入字符串是否为空
        args:
            两个需要判断的字符串
        return:
            bool
        """
        if (str1 == "") or (str2 == ""):
            return True
        return False

    def is_student_exist(self, username):
        """
        func:通过学号判断学生是否存在
        args:
            username：需要判断的学号
        return:
            bool
        """
        if self.cursor.execute("select * from user where username=%d" % username) != 0:
            return True
        return False

    def is_student_passwd_correct(self, username, passwd):
        """
        func:判断学生的用户名及密码是否匹配
        args:
            username：需要判断的学号
            passwd:需要判断的密码
        return:
            bool
        """
        if self.cursor.execute("select * from user where username=%d and passwd='%s'" % (username, passwd)) != 0:
            return True
        return False

    def get_course_list(self):
        """
        func:得到现有的课程列表
        args:
        return:
            包含了课程列表的元组，格式为
            ((课程id1，课程名1)，(课程id2，课程名2)......)
        """
        self.cursor.execute("select * from course")
        return self.cursor.fetchall()

    def course_exist(self, courseid):
        """
        func:查看课程是否存在
        args:
            courseid:要查看的课程id
        return:
            bool
        """
        if self.cursor.execute("select * from course where courseid = %d" % courseid) != 0:
            return True
        return False

    def course_have_been_selected(self, studentid, courseid):
        """
        func:查询某位学生是否已经选择了某课程
        args:
            studentid：要查看的学生id
            courseid:要查看的课程id
        return:
            bool
        """
        if self.cursor.execute(
                "select * from selection where studentid = %d and courseid = %d" % (studentid, courseid)) != 0:
            return True
        return False

    def select(self, studentid, courseid):
        """
        func:某位学生选课
        args:
            studentid：要选课的学生id
            courseid:要选择的课程id
        return:
            None
        """
        self.cursor.execute("insert into selection values(%d,%d)" % (studentid, courseid))
        self.database.commit()

    def get_student_course(self, studentid):
        """
        func:获取某位同学已经选择的课程
        args:
            studentid：要查看的学生id
        return:
            包含课程信息的列表，元素均为字符串
            [课程名1，课程名2...]
        """
        self.cursor.execute("select * from selection where studentid=%d" % studentid)
        t = list()
        for i in self.cursor.fetchall():
            self.cursor.execute("select coursename from course where courseid=%d" % i[1])
            t.append((i[1], self.cursor.fetchall()[0][0]))
        return t

    def delete_course_from_student(self, studentid, courseid):
        """
        func:在某位学生的选课表中删除一门课程
        args:
            studentid：要删除课程的学生id
            courseid：要删除的课程id
        return:
            None
        """
        self.cursor.execute("delete from selection where studentid = %d and courseid = %d" % (studentid, courseid))
        self.database.commit()

    def get_student_list(self):
        """
        func:获得所有学生id及其姓名
        args:
        return:
            一个元组，结构为
            ((学生1id，学生1姓名),(学生2id，学生2姓名)...)
        """
        self.cursor.execute("select * from student")
        return self.cursor.fetchall()

    def get_student_name(self, studentid):
        """
        func:从学生id获得学生姓名
        args:
            studentid：学生id
        return:
            str(学生姓名)
        """
        self.cursor.execute("select * from student where id=%d" % studentid)
        return self.cursor.fetchall()[0][1]

    def add_student(self, studid, studname):
        """
        func:向数据库添加学生
        args:
            studid：学生id
            studname：学生姓名
        return:
            None
        """
        self.cursor.execute("insert into student values(%d,'%s')" % (studid, studname))
        self.cursor.execute("insert into user values(%d,%d)" % (studid, studid))
        self.database.commit()

    def course_exist_by_name(self, coursename):
        """
        func:判断名为coursename的课程是否存在
        args:
            coursename：课程名
        return:
            bool
        """
        if self.cursor.execute("select * from course where coursename='%s'" % coursename) != 0:
            return True
        return False

    def add_course(self, coursename):
        """
        func:添加课程
        args:
            coursename：要添加的课程名，课程id由数据库决定
        return:
            None
        """
        self.cursor.execute("insert into course values(%s,'%s')" % ("NULL", coursename))
        self.database.commit()
# sql = mysql(address='1.15.7.2',port=3306,user='root',passwd='root',char_set="utf-8")
# mysql(address='1.15.7.2',port=3306,user='root',passwd='root',char_set='utf8')
#
# # sql.select()
# -*- coding: UTF-8 -*-

class menu():
    @staticmethod
    def welcome():
        print("欢迎来到选课系统")

    @staticmethod
    def get_username_passwd_str():
        str1 = input("请输入你的用户名：")
        str2 = input("请输入你的密码：")
        return str1, str2

    @staticmethod
    def wrong_passwd():
        print("密码错误，请重新登陆")

    @staticmethod
    def empty_input():
        print("用户名或密码不能为空")

    @staticmethod
    def inexist_username():
        print("用户名不存在")

    @staticmethod
    def student_top_menu():
        print("""
			操作列表：
			1、选课
			2、查看已选课程
			3、查看所有课程
			4、退课
			0、退出登陆
		""")

    @staticmethod
    def get_input_order():
        return int(input("请输入要进行的操作序号"))

    @staticmethod
    def print_course_list(courselist):
        for i in courselist:
            print("%d  %s" % (i[0], i[1]))

    @staticmethod
    def please_select():
        print("请输入要选择的课程代号输入0退出选课：")

    @staticmethod
    def inexist_course_id():
        print("所选课程不存在")

    @staticmethod
    def course_have_been_selected():
        print("你已经选择该课程")

    @staticmethod
    def select_ok():
        print("选课成功")

    @staticmethod
    def print_student_selected_course(course):
        print("你已经选择了如下课程")
        for i in course:
            print("%d  %s" % (i[0], i[1]))

    @staticmethod
    def select_course_to_exit():
        print("请输入要退选的课程代号：")

    @staticmethod
    def exit_ok():
        print("退课成功")

    @staticmethod
    def have_not_chosen():
        print("你没有选择该课程")

    @staticmethod
    def print_student_list(student_list):
        for i in student_list:
            print("Student ID: %d, Student Name: %s" % (i[0], i[1]))

    @staticmethod
    def to_file(studentid, studentname, coursetuple, file):
        """
        将所给信息按照格式写入到文本文件中
        """
        file.write("%s\t%d\t" % (studentname, studentid))
        for i in coursetuple:
            file.write("%d-%s\t" % (i[0], i[1]))
        file.write('\n')

    @staticmethod
    def admin_top_menu():
        print("""
		1、查看所有课程及其id
		2、查看所有同学及其id
		3、查看所有同学及其id和所选课程
		4、查看某位同学所选课程
		5、添加学生信息
		6、添加课程信息
		7、导出学生选课表
		0、退出程序
		""")


# -*- coding: UTF-8 -*-


# 初始化变量
menu = menu()
db = mysql(address='minio.gwozai.com',port=3306,user='root',passwd='root',char_set='utf8')

# 主循环
while True:
    # 打印欢迎信息
    menu.welcome()

    # 输入用户名及密码
    input_username_str, input_passwd_str = menu.get_username_passwd_str()

    # 判断输入是否为空，为空则不继续
    if db.is_empty_input(input_username_str, input_passwd_str) == True:
        menu.empty_input()
        continue

    # 判断用户名是否为管理员用户名，是则验证密码进入管理员模式，否则去学生数据库验证密码
    if db.is_admin(input_username_str) == True:
        # 在管理员数据库验证密码
        if db.is_admin_passwd_correct(input_username_str, input_passwd_str) == True:
            while True:

                # 显示管理员顶级菜单，读入操作代码
                menu.admin_top_menu()
                try:
                    op = menu.get_input_order()
                except:
                    print("输入不合法，请重新输入")
                    continue

                # 1、查看所有课程及其id
                if op == 1:
                    menu.print_course_list(db.get_course_list())
                # 2、查看所有同学及其id
                elif op == 2:
                    menu.print_student_list(db.get_student_list())

                # 3、查看所有同学及其id和所选课程
                elif op == 3:
                    # menu.print_student_course_list(db.get_student_course_list())
                    for op_ in db.get_student_list():
                        print("Student ID: %d, Student Name: %s. Selected:" % (op_[0], op_[1]))
                        menu.print_student_selected_course(db.get_student_course(op_[0]))
                # 4、查看某位同学所选课程
                elif op == 4:
                    print("请输入学生学号")
                    try:
                        op_ = menu.get_input_order()
                    except:
                        print("输入不合法")
                        continue

                    if db.is_student_exist(op_) == False:
                        menu.inexist_username()
                        continue
                    menu.print_student_selected_course(db.get_student_course(op_))

                # 5、添加学生信息
                elif op == 5:
                    print("请输入要添加的学生学号")
                    try:
                        studid = menu.get_input_order()
                    except:
                        print("输入不合法")
                        continue
                    if db.is_student_exist(studid) == True:
                        print("True")
                        print("学生已经存在，姓名为", db.get_student_name(studid))
                        continue
                    print("False")
                    print("请输入要添加的学生姓名")
                    studname = input()
                    if studname == "":
                        print("学生姓名不能为空")
                        continue
                    db.add_student(studid, studname)
                    print("添加学生成功")
                # 6、添加课程信息
                elif op == 6:
                    coursename = input("请输入要添加的课程名称")
                    if coursename == "":
                        print("课程名称不能为空")
                        continue
                    if db.course_exist_by_name(coursename) == True:
                        print("课程已经存在")
                        continue
                    db.add_course(coursename)
                    print("添加课程成功")

                # 7、导出学生选课表
                elif op == 7:
                    print("学生选课表将导出到程序目录下的output文件夹下")

                    # 写入文件时，将会把旧文件覆盖
                    # .csv文件使用utf8编码
                    # 每条字段之间用tab制表符即'\t'分隔
                    # 每条记录之间用回车符分隔
                    # 可以在excel中打开
                    # 打开方式为Excel 2010 -> 菜单栏选择'数据' -> 选择自文本 ->选择文件打开 -> 选择编码utf8
                    file = open("./output/chart.csv", "wt")
                    file.write("姓名\t学号\t所选课程\n")
                    for op_ in db.get_student_list():
                        menu.to_file(op_[0], op_[1], db.get_student_course(op_[0]), file)
                    file.close()

                elif op == 0:
                    break
        else:
            menu.wrong_passwd()
    else:
        input_username_int = db.username2int(input_username_str)
        if input_username_int is None:
            menu.inexist_username()
            continue
        if db.is_student_exist(input_username_int) == False:
            menu.inexist_username()
            continue
        if db.is_student_passwd_correct(input_username_int, input_passwd_str) == True:
            while True:
                menu.student_top_menu()
                try:
                    op = menu.get_input_order()
                except:
                    print("输入不合法，请重新输入")
                    continue
                if op == 0:
                    break
                # 1、选课
                elif op == 1:
                    menu.print_course_list(db.get_course_list())
                    print("输入0退出选课")
                    while True:
                        menu.please_select()
                        try:
                            op_ = menu.get_input_order()
                        except:
                            print("输入不合法，请重新输入课程编号")
                            continue
                        if op_ == 0:
                            break
                        if db.course_exist(op_) == False:
                            menu.inexist_course_id()
                            continue
                        if db.course_have_been_selected(input_username_int, op_) == True:
                            menu.course_have_been_selected()
                            continue
                        db.select(input_username_int, op_)
                        menu.select_ok()
                # 2、查看已选课程
                elif op == 2:
                    menu.print_student_selected_course(db.get_student_course(input_username_int))
                # 3、查看所有课程
                elif op == 3:
                    menu.print_course_list(db.get_course_list())
                # 4、退课
                elif op == 4:
                    menu.print_student_selected_course(db.get_student_course(input_username_int))
                    while True:
                        menu.select_course_to_exit()
                        try:
                            op_ = menu.get_input_order()
                        except:
                            print("输入不合法，请重新输入课程编号")
                            continue
                        if op_ == 0:
                            break
                        if db.course_exist(op_) == False:
                            menu.inexist_course_id()
                            continue
                        if db.course_have_been_selected(input_username_int, op_) == True:
                            db.delete_course_from_student(input_username_int, op_)
                            menu.exit_ok()
                        else:
                            menu.have_not_chosen()
        else:
            menu.wrong_passwd()

# 1120170001


